/**
 * 
 */
package com.googlecode.xcarve.config.provider;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import com.googlecode.xcarve.common.config.ServerConfig;
import com.googlecode.xcarve.exception.CarveException;
import com.googlecode.xcarve.netty.server.NettyServer;
import com.googlecode.xcarve.netty.server.ServiceExport;
import com.googlecode.xcarve.zk.ZookeeperFactory;

/**
 * @author duxinyun
 *
 */
public class ServiceProvider extends AbstractServiceProvider implements ApplicationListener<ContextRefreshedEvent>{
	
	public transient Object       ref;
	
	static final Logger logger = LoggerFactory.getLogger(ServiceProvider.class);
	
	public Object getRef() {
		return ref;
	}

	public void setRef(Object ref) {
		if( ref == null ){
			throw new IllegalArgumentException(" service field [ref] cannot be null.");
		}
		if( !this.getInterfaceClass().isAssignableFrom( ref.getClass() )){
			throw new IllegalArgumentException("field ref = "+ref.getClass().getName() +" is not represented "+ this.getInterfaceName());
		}
		this.ref = ref;
		setInterfaceRefName(ref.getClass().getName());
	}
 


	/* (non-Javadoc)
	 * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
	 */
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if(this.isExported()){
			return ;
		}
		ServiceExport.export(getInterfaceClass(), ref);
		Map<String,NettyServer> serverMap = getServerMap();
		NettyServer server = serverMap.get(getAddress());
		if(server == null){
			synchronized (this) {
				if(server == null){
					ServerConfig config  = new ServerConfig();
					config.setHost(getHost());
					config.setRemotePort(getPort());
					try {
						server = new NettyServer(config);
						logger.info("xcarver start netty transport. address={}", getAddress());
						serverMap.put(getAddress(), server);
						Runtime.getRuntime().addShutdownHook(new Thread(){
							@Override
							public void run() {
								close();
							}
						});
					} catch (CarveException e) {
						throw new RuntimeException(e);
					}
				}
			}
		}
		export();
	}
 
}
